﻿using System.Collections;
using Infrastructure;
using Infrastructure.Model;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using NLog;
using SqlSugar.IOC;
using ZR.Infrastructure.Resolver;
using ZR.ServiceCore.Model;

namespace ZR.ServiceCore.Filters;
public class DataFieldFilter : ActionFilterAttribute
{
    private static readonly Logger Logger = LogManager.GetCurrentClassLogger();

    public DataFieldFilter(Type resultType)
    {
        ResultType = resultType;
    }

    public DataFieldFilter()
    {
    }

    public Type ResultType { get; set; }
    
    public string Path { get; set; }
    
    public override void OnResultExecuting(ResultExecutingContext context)
    {
        // var url = httpContext.Request.Path;
        var info = JwtUtil.GetLoginUser(context.HttpContext);
        var roleIds = info.Roles.Select(it => it.RoleId).ToList();
        // var list = DbScoped.SugarScope.Queryable<PoRequirement>().ToList();
        var list = DbScoped.SugarScope.Queryable<SysField>()
            .LeftJoin<SysRoleField>((sf, srf) => sf.Id == srf.FieldId)
            .Where((sf, srf) => roleIds.Contains(srf.RoleId))
            .ToList();
        
        // 获取原始的结果
        var originalResult = context.Result as ContentResult;
        var apiResult = (JsonConvert.DeserializeObject<ApiResult>(originalResult?.Content!)) as ApiResult;
        // 创建泛型类型
        var resObj = typeof(JObject).GetMethod("ToObject", Type.EmptyTypes)?
            .MakeGenericMethod(ResultType).Invoke(apiResult?["data"], null)!;
        SetPropertiesToNull(resObj, list.Select(it => it.FieldName).ToList());
        // var json = JsonConvert.SerializeObject(resObj, new JsonSerializerSettings
        // {
        //     ContractResolver = new CamelCasePropertyNamesContractResolver()
        // });
        // var jObject = JObject.Parse(json);
        apiResult["data"] = resObj;
        var jsonRes = JsonConvert.SerializeObject(apiResult, new JsonSerializerSettings
        {
            ContractResolver = new CamelCasePropertyNamesContractResolver()
        });
        // JsonConvert.SerializeObject(apiResult, new JsonSerializerSettings
        // {
        //     ContractResolver = new JsonPropertyContractResolver(
        //         list.Select(it => ToLowerFirstLetter(it.FieldName)).ToList()
        //     )
        // })
        context.Result = new ContentResult{ Content = jsonRes,
            ContentType = "application/json"} ;
        base.OnResultExecuting(context);
    }

    private static void SetPropertiesToNull(object obj, IEnumerable<string> props)
    {
        var type = obj.GetType();
        var properties = type.GetProperties();
        foreach (var property in properties)
        {
            if (obj.IsEmpty())
            {
                return;
            }
            if (props.Contains(property.Name))
            {
                property.SetValue(obj, null);
            }
            else if (property.PropertyType.IsArray)
            {
                var arrayValue = (Array)property.GetValue(obj);
                if (arrayValue != null)
                {
                    foreach (var element in arrayValue)
                    {
                        SetPropertiesToNull(element, props);
                    }
                }
            }
            else if (property.PropertyType.IsGenericType &&
                         property.PropertyType.GetGenericTypeDefinition() == typeof(List<>))
            {
                // 属性的类型是 List<T>
                var listValue = (IEnumerable)property.GetValue(obj);
                if (listValue != null)
                {
                    foreach (var element in listValue)
                    {
                        SetPropertiesToNull(element, props);
                    }
                }
            }
            else if (property.PropertyType.GetInterface("IDictionary") != null ||
                     property.PropertyType.GetInterface("IDictionary`2") != null)
            {
                
            }
            else if (property.PropertyType.IsClass && property.PropertyType != typeof(string))
            {
                var name = property.Name;
                var prop = property.GetValue(obj);
                SetPropertiesToNull(prop, props);
            }
        }
    }

    private static string ToLowerFirstLetter(string str)
    {
        if (!str.IsNotEmpty())
        {
            return str;
        }
        var charArray = str.ToCharArray();
        charArray[0] = char.ToLower(charArray[0]);
        return new string(charArray);
    }
}